package pers.chao.tool.thread.pool.impl;

import pers.chao.tool.thread.pool.IExecutor;
import pers.chao.tool.thread.pool.IRealExecutor;

import java.security.InvalidParameterException;
import java.util.List;
import java.util.concurrent.*;

/**
 * Description: 任务提交、管理、线程池管理
 *
 * @author W.Chao
 * @date 2020/12/13 22:33
 **/
@SuppressWarnings("all")
public class ThreadExecutor implements IExecutor {
	private final IRealExecutor realExecutor;

	private ExecutorService getExecutor() {
		return realExecutor;
	}

	public ThreadExecutor(IRealExecutor executor) {
		this.realExecutor = executor;
	}

	@Override
	public void execute(String name, Runnable runnable) {
		synchronized (realExecutor.getTaskNameMap()) {
			realExecutor.getTaskNameMap().put(runnable, name);
		}
		realExecutor.execute(runnable);
	}

	@Override
	public <T> Future<T> submit(String name, Runnable task, T result) {
		if (task == null) throw new NullPointerException();
		RunnableFuture<T> futureTask = null;
		futureTask = new FutureTask(task, result);
		execute(name, futureTask);
		return futureTask;
	}

	@Override
	public Future<?> submit(String name, Runnable task) {
		if (task == null) throw new NullPointerException();
		RunnableFuture<Void> futureTask = null;
		futureTask = new FutureTask(task, null);
		execute(name, futureTask);
		return futureTask;
	}

	@Override
	public <T> Future<T> submit(String name, Callable<T> task) {
		if (task == null) throw new NullPointerException();
		RunnableFuture<T> futureTask = null;
		futureTask = new FutureTask(task);
		execute(name, futureTask);
		return futureTask;
	}

	@Override
	public boolean remove(Runnable command) {
		return realExecutor.remove(command);
	}

	@Override
	public boolean isShutdown() {
		return realExecutor.isShutdown();
	}

	@Override
	public String getPrefixName() {
		return realExecutor.getPrefixName();
	}

	private void shutdown() {
		realExecutor.shutdown();
	}

	private List<Runnable> shutdownNow() {
		return realExecutor.shutdownNow();
	}

	/**
	 * 暴露内部线程池执行器
	 */
	public static class Exposed {
		private final ThreadExecutor threadExecutor;

		public Exposed(IExecutor threadExecutor) {
			if (threadExecutor instanceof ThreadExecutor) {
				this.threadExecutor = (ThreadExecutor) threadExecutor;
			} else {
				throw new InvalidParameterException("The exposed only support the ThreadExecutor instance!");
			}
		}

		public ExecutorService getExecutor() {
			return this.threadExecutor.getExecutor();
		}

		public void shutdown() {
			this.threadExecutor.shutdown();
		}

		public List<Runnable> shutdownNow() {
			return this.threadExecutor.shutdownNow();
		}
	}
}
